package smallfrench.moteur.biblio;

import smallfrench.moteur.biblio.err.ErreurParametres;
import smallfrench.moteur.interp.RObjet;


public class RClasseEnumeration extends RClasse {

	public static final RClasseEnumeration CLASSE = new RClasseEnumeration();

	private RClasseEnumeration() {

		super(new RClasse[] {RClasse.CLASSE});

		champs.put("obtenirNomMembre", fnObtenirNomMembre);

	}

	@Override
	public RObjet appeler(RObjet moi, RObjet[] args) {

		String[] chaines = new String[args.length];

		for (int i = 0; i < args.length; i++) {

			RObjet param = args[i];

			if (! (param instanceof RChaine))
				throw ErreurParametres.nouvelleException();

			RChaine rchaine = (RChaine) param;
			String membre = rchaine.valeur;

			if (! estValide(membre))
				throw ErreurParametres.nouvelleException();

			chaines[i] = membre;
		}
		return new REnumeration(chaines);
	}


	private static boolean estValide(String nom) {
		for (int i = 0; i < nom.length(); i++) {
			char c = nom.charAt(i);
			boolean caractereValide = (c == '_') || (c >= 'A' && c <= 'Z');
			if (! caractereValide) {
				return false;
			}
		}
		return true;
	}



	@Override
	public RChaine enChaine() {
		return new RChaine("Enumeration");
	}



	private static abstract class Fonction extends RFonction {

		public abstract RObjet appeler2(REnumeration moi, RObjet[] params);

		@Override
		public final RObjet appeler(RObjet moi, RObjet[] params) {
			if (moi instanceof REnumeration)
				return appeler2((REnumeration)moi, params);
			throw new RuntimeException(moi.getClass().toString());
		}
	}


	private final Fonction fnObtenirNomMembre = new Fonction() {

		@Override
		public RObjet appeler2(REnumeration moi, RObjet[] params) {

			if (params.length != 1)
				throw ErreurParametres.nouvelleException();

			RObjet param = params[0];
			if (! (param instanceof REntier))
				throw ErreurParametres.nouvelleException();

			REntier objetIndex = (REntier) param;
			int index = objetIndex.getValeurInt();

			String nomMembre = moi.getNomMembre(index);
			if (nomMembre == null)
				throw ErreurParametres.nouvelleException();

			return new RChaine(nomMembre);
		}
	};

}
